package com.test.aspectdemo;

import android.util.Log;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class MyAspect1 {
    private static final String TAG = "MyAspect1";

    // 定义切点，匹配所有 public 方法
    // @Pointcut("execution(public * *(..))")

    // execution(方法修饰符（可选） 返回类型 方法名 参数 异常模式（可选）)

    // region 匹配带有某注解的所有方法
    @Pointcut("execution(@android.webkit.JavascriptInterface * *(..))")
    public void onJavascriptInterface() {
    }

    @Around("onJavascriptInterface()")
    public Object onJavascriptInterface(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        String methodName = joinPoint.getSignature().getName();

        Log.d(TAG, " ");

        Log.d(TAG, "onJavascriptInterface: 方法" + methodName + "前插入一条数据");

        Object[] args = joinPoint.getArgs(); // 对象不为null，里面元素为empty
        if (args != null) {
            Log.d(TAG, "onJavascriptInterface: 入参个数=" + args.length);
            for (int i = 0; i < args.length; i++) {
                Log.d(TAG, "onJavascriptInterface: 入参" + (i + 1) + "=" + args[i]);
            }
        }

        Object result = joinPoint.proceed();

        Log.d(TAG, "onJavascriptInterface: 方法" + methodName + "耗时=" + (System.currentTimeMillis() - startTime));
        return result;
    }
    // endregion

    // region 匹配某个类中的所有方法
    @Pointcut("execution(* com.test.aspectdemo.MainActivity.*(..))")
    public void allMethodInOneClass() {
    }

    // 定义切面，绑定到切点上
    @Around("allMethodInOneClass()")
    public Object onHook(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        String methodName = joinPoint.getSignature().getName();

        Log.d(TAG, " ");

        Log.d(TAG, "onHook: 方法" + methodName + "前插入一条数据");

        Object result = joinPoint.proceed();

        Log.d(TAG, "onHook: 方法" + methodName + "耗时=" + (System.currentTimeMillis() - startTime));
        return result;
    }
    // endregion

    // region 匹配某个特定方法
    // @Pointcut("call(public void com.test.aspectdemo.MainActivity.onResume(..))") // 不行
    // @Pointcut("call(void com.test.aspectdemo.MainActivity.onResume(..))") // 不行
    // @Pointcut("call(* com.test.aspectdemo.MainActivity.onResume(..))") // 不行
    // @Pointcut("execution(* com.test.aspectdemo.MainActivity.onResume(..))") // 可以
    @Pointcut("execution(void com.test.aspectdemo.MainActivity.onResume(..))") // 可以
    // @Pointcut("execution(public void com.test.aspectdemo.MainActivity.onResume(..))") // 不行
    public void onResume() {
    }

    @Before("onResume()")
    public void before(JoinPoint joinPoint) {

        Object target = joinPoint.getTarget();
        Log.d(TAG, "通过AOP获取类=" + target.getClass().getName());

        if (target instanceof MainActivity) {
            Log.d(TAG, "通过AOP获取类中成员变量=" + ((MainActivity) target).getPubString());
        }
    }
    // endregion

}

/*
2023-06-10 21:35:10.654 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法onCreate前插入一条数据
2023-06-10 21:35:10.654 10144-10144/com.test.aspectdemo D/MainActivity: onCreate:
2023-06-10 21:35:11.141 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法onCreate耗时=487
2023-06-10 21:35:11.159 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法onResume前插入一条数据
2023-06-10 21:35:11.173 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 方法test前插入一条数据
2023-06-10 21:35:11.173 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 入参个数=0
2023-06-10 21:35:11.173 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法test前插入一条数据
2023-06-10 21:35:11.173 10144-10144/com.test.aspectdemo D/MainActivity: test:
2023-06-10 21:35:11.173 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法test耗时=0
2023-06-10 21:35:11.173 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 方法test耗时=1
2023-06-10 21:35:11.174 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 方法testInt前插入一条数据
2023-06-10 21:35:11.174 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 入参个数=1
2023-06-10 21:35:11.174 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 入参1=1
2023-06-10 21:35:11.174 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法testInt前插入一条数据
2023-06-10 21:35:11.174 10144-10144/com.test.aspectdemo D/MainActivity: testInt: 1
2023-06-10 21:35:11.174 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法testInt耗时=0
2023-06-10 21:35:11.175 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 方法testInt耗时=0
2023-06-10 21:35:11.175 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 方法testString前插入一条数据
2023-06-10 21:35:11.175 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 入参个数=3
2023-06-10 21:35:11.175 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 入参1=1
2023-06-10 21:35:11.175 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 入参2=22
2023-06-10 21:35:11.175 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 入参3=333
2023-06-10 21:35:11.175 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法testString前插入一条数据
2023-06-10 21:35:11.177 10144-10144/com.test.aspectdemo D/MainActivity: testString: 1 22 333
2023-06-10 21:35:11.177 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法testString耗时=2
2023-06-10 21:35:11.177 10144-10144/com.test.aspectdemo D/MyAspect1: onJavascriptInterface: 方法testString耗时=2
2023-06-10 21:35:11.177 10144-10144/com.test.aspectdemo D/MyAspect1: onHook: 方法onResume耗时=18
2023-06-10 21:35:11.331 10144-10144/com.test.aspectdemo I/TopResumedActivityChangeItem: execute start, ActivityClientRecord = ActivityRecord{6d208e6 token=android.os.BinderProxy@bf6764f {com.test.aspectdemo/com.test.aspectdemo.MainActivity}}
2023-06-10 21:35:11.333 10144-10144/com.test.aspectdemo I/TopResumedActivityChangeItem: execute start, ActivityClientRecord = ActivityRecord{6d208e6 token=android.os.BinderProxy@bf6764f {com.test.aspectdemo/com.test.aspectdemo.MainActivity}}

* */